/*!
 * mdtoolbar.js - MarkdownToolbar/HtmlToolbar 独立工具栏库
 * 支持 Markdown 编辑器和 HTML 编辑器，支持 CodeMirror 实例
 * 
 * 用法示例：
 *   const mdToolbar = MarkdownToolbar({ container, editor });
 *   const htmlToolbar = HtmlToolbar({ container, editor });
 */

(function (global) {
    // ======= 通用工具方法 =======
    function insertAtCursor(editor, before, after, placeholder = '') {
        const doc = editor.getDoc();
        const sel = doc.getSelection();
        const text = sel || placeholder;
        doc.replaceSelection(before + text + after);
        if (!sel && placeholder) {
            const cursor = doc.getCursor();
            doc.setSelection(
                { line: cursor.line, ch: cursor.ch - after.length - placeholder.length },
                { line: cursor.line, ch: cursor.ch - after.length }
            );
        }
        editor.focus();
    }
    function insertLineAtCursor(editor, lineText) {
        const doc = editor.getDoc();
        const cursor = doc.getCursor();
        doc.replaceRange(lineText + '\n', { line: cursor.line, ch: 0 });
        editor.focus();
    }
    function insertList(editor, ordered = false) {
        const doc = editor.getDoc();
        const sel = doc.getSelection();
        const lines = sel ? sel.split('\n') : ['列表项'];
        const prefix = ordered ? (i) => `${i + 1}. ` : () => '- ';
        const newText = lines.map((line, i) => prefix(i) + (line.trim() || '列表项')).join('\n');
        doc.replaceSelection(newText);
        editor.focus();
    }

    // ======= MarkdownToolbar =======
    function MarkdownToolbar(options) {
        if (!(this instanceof MarkdownToolbar)) return new MarkdownToolbar(options);

        this.container = options.container;
        this.editor = options.editor;
        this.config = options.config || MarkdownToolbar.defaultConfig(this);

        // 绑定工具方法到实例
        this.insertAtCursor = (before, after, placeholder = '') =>
            insertAtCursor(this.editor, before, after, placeholder);
        this.insertLineAtCursor = (lineText) =>
            insertLineAtCursor(this.editor, lineText);
        this.insertList = (ordered = false) =>
            insertList(this.editor, ordered);

        this._render();
        this._bind();
        return this;
    }

    MarkdownToolbar.defaultConfig = function (toolbarInstance) {
        return [
            {
                action: 'bold',
                icon: 'format_bold',
                tip: '加粗',
                handler: function () { this.insertAtCursor('**', '**', '加粗文本'); }
            },
            {
                action: 'italic',
                icon: 'format_italic',
                tip: '斜体',
                handler: function () { this.insertAtCursor('*', '*', '斜体文本'); }
            },
            { divider: true },
            {
                action: 'heading',
                icon: 'title',
                tip: '标题',
                handler: function () { this.insertLineAtCursor('# 标题'); }
            },
            {
                action: 'quote',
                icon: 'format_quote',
                tip: '引用',
                handler: function () { this.insertLineAtCursor('> '); }
            },
            { divider: true },
            {
                action: 'code',
                icon: 'code',
                tip: '代码块',
                handler: function () { this.insertAtCursor('\n```\n', '\n```\n', '代码内容'); }
            },
            {
                action: 'link',
                icon: 'link',
                tip: '插入链接',
                handler: function () {
                    const url = prompt('请输入链接地址：', 'https://');
                    if (url) this.insertAtCursor('[', `](${url})`, '链接文本');
                }
            },
            {
                action: 'image',
                icon: 'image',
                tip: '插入图片',
                handler: function () {
                    const url = prompt('请输入图片链接：', 'https://');
                    if (url) this.insertAtCursor('![图片描述](', ')', url);
                }
            },
            { divider: true },
            {
                action: 'ul',
                icon: 'format_list_bulleted',
                tip: '无序列表',
                handler: function () { this.insertList(false); }
            },
            {
                action: 'ol',
                icon: 'format_list_numbered',
                tip: '有序列表',
                handler: function () { this.insertList(true); }
            },
            { divider: true },
            {
                action: 'table',
                icon: 'table_chart',
                tip: '插入表格',
                handler: function () {
                    this.insertLineAtCursor(
                        '| 左对齐 | 居中 | 右对齐 |\n| :--- | :---: | ---: |\n| 内容1 | 内容2 | 内容3 |'
                    );
                }
            },
            {
                action: 'hr',
                icon: 'horizontal_rule',
                tip: '分割线',
                handler: function () { this.insertLineAtCursor('---'); }
            }
        ];
    };

    // ======= HtmlToolbar =======
    function HtmlToolbar(options) {
        if (!(this instanceof HtmlToolbar)) return new HtmlToolbar(options);

        this.container = options.container;
        this.editor = options.editor;
        this.config = options.config || HtmlToolbar.defaultConfig(this);

        // 绑定工具方法到实例
        this.insertAtCursor = (before, after, placeholder = '') =>
            insertAtCursor(this.editor, before, after, placeholder);
        this.insertLineAtCursor = (lineText) =>
            insertLineAtCursor(this.editor, lineText);

        this._render();
        this._bind();
        return this;
    }

    HtmlToolbar.defaultConfig = function (toolbarInstance) {
        return [
            {
                action: 'bold',
                icon: 'format_bold',
                tip: '加粗',
                handler: function () { this.insertAtCursor('<b>', '</b>', '加粗文本'); }
            },
            {
                action: 'italic',
                icon: 'format_italic',
                tip: '斜体',
                handler: function () { this.insertAtCursor('<i>', '</i>', '斜体文本'); }
            },
            { divider: true },
            {
                action: 'heading',
                icon: 'title',
                tip: '标题',
                handler: function () { this.insertLineAtCursor('<h1>标题</h1>'); }
            },
            {
                action: 'quote',
                icon: 'format_quote',
                tip: '引用',
                handler: function () { this.insertLineAtCursor('<blockquote>引用内容</blockquote>'); }
            },
            { divider: true },
            {
                action: 'code',
                icon: 'code',
                tip: '代码块',
                handler: function () { this.insertAtCursor('<pre><code>', '</code></pre>', '代码内容'); }
            },
            {
                action: 'link',
                icon: 'link',
                tip: '插入链接',
                handler: function () {
                    const url = prompt('请输入链接地址：', 'https://');
                    if (url) this.insertAtCursor('<a href="' + url + '">', '</a>', '链接文本');
                }
            },
            {
                action: 'image',
                icon: 'image',
                tip: '插入图片',
                handler: function () {
                    const url = prompt('请输入图片链接：', 'https://');
                    if (url) this.insertLineAtCursor('<img src="' + url + '" alt="图片描述">');
                }
            },
            { divider: true },
            {
                action: 'ul',
                icon: 'format_list_bulleted',
                tip: '无序列表',
                handler: function () { this.insertLineAtCursor('<ul><li>列表项</li></ul>'); }
            },
            {
                action: 'ol',
                icon: 'format_list_numbered',
                tip: '有序列表',
                handler: function () { this.insertLineAtCursor('<ol><li>列表项</li></ol>'); }
            },
            { divider: true },
            {
                action: 'table',
                icon: 'table_chart',
                tip: '插入表格',
                handler: function () {
                    this.insertLineAtCursor(
                        '<table>\n<tr><th>表头1</th><th>表头2</th></tr>\n<tr><td>内容1</td><td>内容2</td></tr>\n</table>'
                    );
                }
            },
            {
                action: 'hr',
                icon: 'horizontal_rule',
                tip: '分割线',
                handler: function () { this.insertLineAtCursor('<hr>'); }
            }
        ];
    };

    // ======= 通用原型方法 =======
    function renderToolbar(config, container) {
        container.innerHTML = '';
        config.forEach(item => {
            if (item.divider) {
                const span = document.createElement('span');
                span.className = 'toolbar-divider';
                container.appendChild(span);
            } else {
                const btn = document.createElement('button');
                btn.type = 'button';
                btn.dataset.action = item.action;
                btn.title = item.tip || item.action;
                btn.setAttribute('aria-label', item.tip || item.action);
                btn.innerHTML = item.iconHtml || `<span class="material-icons">${item.icon}</span>`;
                container.appendChild(btn);
            }
        });
    }

    function bindToolbarEvents(toolbar, config, container) {
        container.addEventListener('click', e => {
            const btn = e.target.closest('button[data-action]');
            if (!btn) return;
            const action = btn.dataset.action;
            const item = config.find(i => i.action === action);
            if (item && typeof item.handler === 'function') {
                item.handler.call(toolbar);
            }
        });
    }

    // MarkdownToolbar 原型
    MarkdownToolbar.prototype._render = function () {
        renderToolbar(this.config, this.container);
    };
    MarkdownToolbar.prototype._bind = function () {
        bindToolbarEvents(this, this.config, this.container);
    };
    MarkdownToolbar.prototype.setActive = function (action, active = true) {
        const btn = this.container.querySelector(`button[data-action="${action}"]`);
        if (btn) btn.classList.toggle('active', !!active);
        return this;
    };
    MarkdownToolbar.prototype.setDisabled = function (action, disabled = true) {
        const btn = this.container.querySelector(`button[data-action="${action}"]`);
        if (btn) btn.disabled = !!disabled;
        return this;
    };
    MarkdownToolbar.prototype.setTip = function (action, tip) {
        const btn = this.container.querySelector(`button[data-action="${action}"]`);
        if (btn) {
            btn.title = tip;
            btn.setAttribute('aria-label', tip);
        }
        return this;
    };
    MarkdownToolbar.prototype.addButton = function (item, position = -1) {
        if (!item || !item.action) return this;
        const btn = document.createElement('button');
        btn.type = 'button';
        btn.dataset.action = item.action;
        btn.title = item.tip || item.action;
        btn.setAttribute('aria-label', item.tip || item.action);
        btn.innerHTML = item.iconHtml || `<span class="material-icons">${item.icon}</span>`;
        if (position < 0 || position >= this.container.children.length) {
            this.container.appendChild(btn);
            this.config.push(item);
        } else {
            this.container.insertBefore(btn, this.container.children[position]);
            this.config.splice(position, 0, item);
        }
        return this;
    };
    MarkdownToolbar.prototype.removeButton = function (action) {
        const btn = this.container.querySelector(`button[data-action="${action}"]`);
        if (btn) btn.remove();
        const idx = this.config.findIndex(i => i.action === action);
        if (idx !== -1) this.config.splice(idx, 1);
        return this;
    };

    // HtmlToolbar 原型（与 MarkdownToolbar 相同）
    HtmlToolbar.prototype._render = MarkdownToolbar.prototype._render;
    HtmlToolbar.prototype._bind = MarkdownToolbar.prototype._bind;
    HtmlToolbar.prototype.setActive = MarkdownToolbar.prototype.setActive;
    HtmlToolbar.prototype.setDisabled = MarkdownToolbar.prototype.setDisabled;
    HtmlToolbar.prototype.setTip = MarkdownToolbar.prototype.setTip;
    HtmlToolbar.prototype.addButton = MarkdownToolbar.prototype.addButton;
    HtmlToolbar.prototype.removeButton = MarkdownToolbar.prototype.removeButton;

    // 导出
    global.MarkdownToolbar = MarkdownToolbar;
    global.HtmlToolbar = HtmlToolbar;
})(window);